#define _GNU_SOURCE     //在源文件开头定义_GNU_SOURCE宏
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <signal.h>
#include <termios.h>

typedef struct sockaddr* SP;

int uartfd;
struct sockaddr_in caddr = {};
socklen_t caddrlen;
unsigned char read_buf[4096] = {};
size_t read_buf_size = sizeof(read_buf);

unsigned char write_buf[4096] = {};
size_t write_buf_size = sizeof(write_buf);


void* pthread_read(void * arg)		//创建线程用以接收数据
{
    int confd = *(int *)arg;
    while(1)
    {
        int res  =  recvfrom(confd,read_buf,read_buf_size,0,(struct sockaddr*)&caddr,&caddrlen);
        write(uartfd, read_buf,res); 
     if(0 >= res)
		{
			printf("网络异常,通信结束!");
			close(confd);
			break ;
		}
       // printf("from %s recv:[%s] bits:%d\n",
			//inet_ntoa(caddr.sin_addr),read_buf,res);
    memset(read_buf,0,read_buf_size);
    }
}

void* pthread_write(void * arg)		//创建线程用以接收数据
{
    int confd = *(int *)arg;
    while(1)
    {
        int ret = read(uartfd, write_buf,write_buf_size);     //一次最多读8个字节数据
        if(ret != 0){
            ret = sendto(confd,write_buf,write_buf_size,0,(struct sockaddr*)&caddr,caddrlen);
        }
        memset(write_buf,0,write_buf_size);
    }
}

void uart_init(int fd){
    struct termios old_cfg;
    if(0>tcgetattr(fd,&old_cfg))
    {
	    exit(-1);
    }

    struct termios new_cfg;

    memset(&new_cfg,0x0,sizeof(struct termios));

    //配置为原始模式
    cfmakeraw(&new_cfg);

    //使能接收
    new_cfg.c_cflag |= CREAD;

    //设置波特率
    cfsetspeed(&new_cfg,B115200);

    //设置数据位大小
    new_cfg.c_cflag &= ~CSIZE;
    new_cfg.c_cflag |= CS8;//数据位为8位

    //设置奇偶校验


    //奇校验使能
    new_cfg.c_cflag |= (PARODD | PARENB);
    new_cfg.c_iflag |= INPCK;
    //偶校验使能
    new_cfg.c_cflag |= PARENB;
    new_cfg.c_cflag &= ~PARODD; /* 清除 PARODD 标志，配置为偶校验 */
    new_cfg.c_iflag |= INPCK;
    //无校验
    new_cfg.c_cflag &= ~PARENB;
    new_cfg.c_iflag &= ~INPCK;

    //设置停止位
    // 将停止位设置为一个比特
    new_cfg.c_cflag &= ~CSTOPB;
    // 将停止位设置为 2 个比特
    new_cfg.c_cflag |= CSTOPB;

    //设置MIN和TIME的值
    new_cfg.c_cc[VTIME] = 0;
    new_cfg.c_cc[VMIN] = 0;
    
    //调用tcflush（）清空缓冲区
    tcflush(fd, TCIOFLUSH);
    
    //调用tcsetattr()将配置写入设备，使其立即生效
    tcsetattr(fd,TCSANOW,&new_cfg);

}

int main(int argc,const char* argv[])
{
     printf("uart init\n");
    
    uartfd = open("/dev/ttyUSB0",O_RDWR|O_NOCTTY| O_NDELAY);
    if(uartfd<0)
    {
	    perror("open error");
	    return -1;
    }
    uart_init(uartfd);
    printf("set up uart success\n");

	//	创建socket
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return EXIT_FAILURE;
	}
	
	//	准备本机通信地址
	struct sockaddr_in srv_addr = {},cli_addr = {};
	srv_addr.sin_family = AF_INET;
	srv_addr.sin_port = htons(7788);
    //这里的“xxx.xx.xx.xx”写本机的ip地址，可以用ifconfig命令查看，windows可以用ipconfig查看
	srv_addr.sin_addr.s_addr = inet_addr("192.168.1.105");
	socklen_t addrlen = sizeof(srv_addr);

	//	绑定
	if(bind(sockfd,(SP)&srv_addr,addrlen))
	{
		perror("bind");
		return EXIT_FAILURE;
	}

	char buf[4096] = {};
	size_t buf_size = sizeof(buf);

     pthread_t tidR;
    pthread_create(&tidR, NULL, pthread_read, &sockfd);

    pthread_t tidW;
    pthread_create(&tidW, NULL, pthread_write, &sockfd);

	for(;;)
	{
		
	}
}	
